package com.ruoyi.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.EqpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.vo.WebSocketVO;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ehcache.EqpStatusCache;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.websocket.WebSocketUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.prt.domain.PrtUserDoc;
import com.ruoyi.prt.domain.vo.PrtCouponVO;
import com.ruoyi.prt.service.IPrtPrintService;
import com.ruoyi.prt.service.IPrtUserDocService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@Component
@ServerEndpoint(value = "/websocket/{token}")
public class WebSocketService {
    private static final Logger log = LoggerFactory.getLogger(WebSocketService.class);

    private static final IPrtUserDocService prtUserDocService = SpringUtils.getBean(IPrtUserDocService.class);
    private static final IPrtPrintService prtPrintService = SpringUtils.getBean(IPrtPrintService.class);
    private static final TokenService tokenService = SpringUtils.getBean(TokenService.class);

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        LoginUser loginUser = tokenService.getLoginUser(token);
        if (loginUser == null) {
            WebSocketUtils.sendErrorMsg(session, MessageUtils.message("prt.ws.login.not"));
            WebSocketUtils.exitSession(session);
            return;
        }
        WebSocketUtils.openSession(session, token, loginUser);
        log.info("WEBSOCKET_用户连接:" + loginUser.getUser().getNickName() + ",当前在线人数为:" + WebSocketUtils.getNum());
        WebSocketUtils.sendSuccessMsg(session, MessageUtils.message("prt.ws.link.success"));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        WebSocketUtils.WebSocketClient client = WebSocketUtils.getClient(session);
        WebSocketUtils.closeSession(session);
        if (client != null) {
            log.info("WEBSOCKET_用户" + client.getToken() + "退出,当前在线人数为:" + WebSocketUtils.getNum());
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        WebSocketUtils.WebSocketClient client = WebSocketUtils.getClient(session);
        log.info("收到用户消息:" + client.getToken() + ",报文:" + message);
        if (StringUtils.isNotBlank(message)) {
            try {
                JSONObject jsonObject = JSON.parseObject(message);
                int state = jsonObject.getInteger("state");
                WebSocketVO data = new WebSocketVO();
                if (jsonObject.containsKey(Constants.DATA)) {
                    data = jsonObject.getObject(Constants.DATA, WebSocketVO.class);
                }

                String docId = data.getDocId();
                PrtUserDoc doc = prtUserDocService.selectPrtUserDocById(docId);
                switch (state) {
                    //获取指定文档的信息
                    case 4:
                        if (StringUtils.isEmpty(doc.getPdfName())) {
                            doc = prtUserDocService.convertToPdf(doc);
                        }
                        AjaxResult result = AjaxResult.success().setData(doc);
                        result.put("status", 5);
                        WebSocketUtils.sendMessage(session, result);
                        break;
                    //提交打印参数
                    case 7:
                        LoginUser loginUser = WebSocketUtils.getLoginUser(session);
                        //判断打印机状态
                        if (EqpStatusCache.getEqpStatus(data.getEqpName()) != EqpStatus.CONNECTED) {
                            WebSocketUtils.sendErrorMsg(session, MessageUtils.message("prt.ws.printer.busy"));
                            return;
                        }
                        if (loginUser == null) {
                            WebSocketUtils.sendErrorMsg(session, MessageUtils.message("prt.ws.login.expire"));
                            return;
                        }
                        data.setToken(client.getToken());
                        data.setUserId(loginUser.getUserId());
                        data.setNickName(loginUser.getUser().getNickName());
                        data.setFileName(doc.getDocName());
                        //1.判断是否可以打印
                        AjaxResult canPrint = prtPrintService.checkCanPrint(data);
                        if (canPrint.isError()) {
                            WebSocketUtils.sendMessage(session, canPrint);
                            return;
                        }
                        PrtCouponVO priceData = (PrtCouponVO) canPrint.getData();
                        data.setPrice(priceData.getPayPrice());
                        //2.拼接打印参数
                        String printPrams = prtPrintService.splitPrintPrams(data);

                        //3.给打印机发送打印请求
                        MqttConsumer.publish(data.getEqpName(), printPrams);
                        WebSocketUtils.sendSuccessMsg(session, MessageUtils.message("prt.ws.printer.start"));
                        break;
                    default:
                }
            } catch (Exception e) {
                WebSocketUtils.sendErrorMsg(session, MessageUtils.message("prt.ws.data.format.error"));
            }
        }
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        WebSocketUtils.WebSocketClient client = WebSocketUtils.getClient(session);
        WebSocketUtils.closeSession(session);
        if (client == null) {
            log.error("WEBSOCKET_错误,原因:" + error.getMessage());
        } else {
            log.error("WEBSOCKET_用户错误:" + client.getToken() + ",原因:" + error.getMessage());
        }
        error.printStackTrace();
    }

}
